package com.itstyle.mytest.service.impl;

import com.itstyle.mytest.common.aop.TestServiceLock;
import com.itstyle.mytest.mapper.MyTestMapper;
import com.itstyle.mytest.service.IMyTestService;
import com.itstyle.seckill.common.entity.Result;
import com.itstyle.seckill.common.entity.Seckill;
import com.itstyle.seckill.common.entity.SuccessKilled;
import com.itstyle.seckill.common.enums.SeckillStatEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author xianguang
 * @date 2019-12-10 11:12
 */
@Service
public class MyTestServieImpl implements IMyTestService {


    @Autowired
    private MyTestMapper testMapper;

    /**
     * 思考：为什么不用synchronized
     * service 默认是单例的，并发下lock只有一个实例
     */
    private Lock lock = new ReentrantLock(true);//互斥锁 参数默认false，不公平锁

    @Override
    @Transactional
    public Result startSeckil(long seckillId, long userId) {
        //查询库存
        Long number = testMapper.selectInventory(seckillId);
        if (number > 0) {
            //查询是否重复下单
            SuccessKilled killed1 = testMapper.selectSuccessKilled(new SuccessKilled(seckillId, userId));
            if (killed1 != null) {
                return Result.error(SeckillStatEnum.REPEAT_KILL);
            }
            //创建订单
            SuccessKilled killed = new SuccessKilled();
            killed.setSeckillId(seckillId);
            killed.setUserId(userId);
            killed.setState((short) 0);
            Timestamp createTime = new Timestamp(new Date().getTime());
            killed.setCreateTime(createTime);
            testMapper.saveOrder(killed);
            //扣库存
            testMapper.minusInventory(seckillId);
            return Result.ok(SeckillStatEnum.SUCCESS);
        } else {
            return Result.error(SeckillStatEnum.END);
        }
    }

    @Override
    @Transactional
    public Result startSeckilLock(long seckillId, long userId) {
        try {
            lock.lock();
            //查询库存
            Long number = testMapper.selectInventory(seckillId);
            if (number > 0) {
                //查询是否重复下单
                SuccessKilled killed1 = testMapper.selectSuccessKilled(new SuccessKilled(seckillId, userId));
                if (killed1 != null) {
                    return Result.error(SeckillStatEnum.REPEAT_KILL);
                }
                //创建订单
                SuccessKilled killed = new SuccessKilled();
                killed.setSeckillId(seckillId);
                killed.setUserId(userId);
                killed.setState((short) 0);
                Timestamp createTime = new Timestamp(new Date().getTime());
                killed.setCreateTime(createTime);
                testMapper.saveOrder(killed);
                //扣库存
                testMapper.minusInventory(seckillId);
                return Result.ok(SeckillStatEnum.SUCCESS);
            } else {
                return Result.error(SeckillStatEnum.END);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return Result.ok(SeckillStatEnum.SUCCESS);
    }

    @Override
    @TestServiceLock
    @Transactional
    public Result startSeckilAopLock(long seckillId, long userId) {
        //查询库存
        Long number = testMapper.selectInventory(seckillId);
        if (number > 0) {
            //查询是否重复下单
            SuccessKilled killed1 = testMapper.selectSuccessKilled(new SuccessKilled(seckillId, userId));
            if (killed1 != null) {
                return Result.error(SeckillStatEnum.REPEAT_KILL);
            }
            //创建订单
            SuccessKilled killed = new SuccessKilled();
            killed.setSeckillId(seckillId);
            killed.setUserId(userId);
            killed.setState((short) 0);
            Timestamp createTime = new Timestamp(new Date().getTime());
            killed.setCreateTime(createTime);
            testMapper.saveOrder(killed);
            //扣库存
            testMapper.minusInventory(seckillId);
            return Result.ok(SeckillStatEnum.SUCCESS);
        } else {
            return Result.error(SeckillStatEnum.END);
        }
    }

    @Override
    @Transactional
    public Result startDBPCC_ONE(long seckillId, long userId) {
        //查询库存
        Long number = testMapper.selectInventoryForUpdate(seckillId);
        if (number > 0) {
            //查询是否重复下单
            SuccessKilled killed1 = testMapper.selectSuccessKilled(new SuccessKilled(seckillId, userId));
            if (killed1 != null) {
                return Result.error(SeckillStatEnum.REPEAT_KILL);
            }
            //创建订单
            SuccessKilled killed = new SuccessKilled();
            killed.setSeckillId(seckillId);
            killed.setUserId(userId);
            killed.setState((short) 0);
            Timestamp createTime = new Timestamp(new Date().getTime());
            killed.setCreateTime(createTime);
            testMapper.saveOrder(killed);
            //扣库存
            testMapper.minusInventory(seckillId);
            return Result.ok(SeckillStatEnum.SUCCESS);
        } else {
            return Result.error(SeckillStatEnum.END);
        }
    }

    @Override
    @Transactional
    public Result startDBPCC_TWO(long seckillId, long userId) {

        //扣库存
        int res = testMapper.minusInventoryL(seckillId); //UPDATE锁表
        if (res > 0) {
            //查询是否重复下单
            SuccessKilled killed1 = testMapper.selectSuccessKilled(new SuccessKilled(seckillId, userId));
            if (killed1 != null) {
                return Result.error(SeckillStatEnum.REPEAT_KILL);
            }
            //创建订单
            SuccessKilled killed = new SuccessKilled();
            killed.setSeckillId(seckillId);
            killed.setUserId(userId);
            killed.setState((short) 0);
            Timestamp createTime = new Timestamp(new Date().getTime());
            killed.setCreateTime(createTime);
            testMapper.saveOrder(killed);
            return Result.ok(SeckillStatEnum.SUCCESS);
        } else {
            return Result.error(SeckillStatEnum.END);
        }
    }

    @Override
    @Transactional
    public Result startDBOCC(long seckillId, long userId) {
        //查询秒杀商品
        Seckill seckill = testMapper.selectSeckillById(seckillId);
        if (seckill.getNumber() > 0) {
            //查询是否重复下单
            SuccessKilled killed1 = testMapper.selectSuccessKilled(new SuccessKilled(seckillId, userId));
            if (killed1 != null) {
                return Result.error(SeckillStatEnum.REPEAT_KILL);
            }

            //扣库存
            int res = testMapper.minusInventoryWithVersion(seckillId, seckill.getVersion());
            if (res > 0) {
                //创建订单
                SuccessKilled killed = new SuccessKilled();
                killed.setSeckillId(seckillId);
                killed.setUserId(userId);
                killed.setState((short) 0);
                Timestamp createTime = new Timestamp(new Date().getTime());
                killed.setCreateTime(createTime);
                testMapper.saveOrder(killed);

                return Result.ok(SeckillStatEnum.SUCCESS);
            } else {
                return Result.error(SeckillStatEnum.END);
            }
        } else {
            return Result.error(SeckillStatEnum.END);
        }
    }

    @Override
    public Result print() {
        System.out.println("print()");
        return null;
    }
}
